﻿namespace System.ServiceModel.DomainServices.Client.ApplicationServices
{
    using System;
    using System.Security.Principal;
    using System.ServiceModel.DomainServices;
    using System.ServiceModel.DomainServices.Client;
    using System.Threading;

    public abstract class AuthenticationOperation : OperationBase
    {
        private IAsyncResult _asyncResult;
        private readonly AuthenticationService _service;
        private readonly SynchronizationContext _synchronizationContext;

        internal AuthenticationOperation(AuthenticationService service, object userState) : base(userState)
        {
            this._synchronizationContext = SynchronizationContext.Current ?? new SynchronizationContext();
            this._service = service;
        }

        protected abstract IAsyncResult BeginCore(AsyncCallback callback);
        private void End(IAsyncResult result)
        {
            object obj2 = null;
            try
            {
                obj2 = this.EndCore(result);
            }
            catch (Exception exception)
            {
                if (exception.IsFatal())
                {
                    throw;
                }
                base.Complete(exception);
                this.RaiseCompletionPropertyChanges();
                return;
            }
            base.Complete(obj2);
            this.RaiseCompletionPropertyChanges();
        }

        protected abstract object EndCore(IAsyncResult asyncResult);
        private void HandleAsyncCompleted(IAsyncResult asyncResult)
        {
            if (this._asyncResult == null)
            {
                this._asyncResult = asyncResult;
            }
            this.RunInSynchronizationContext(delegate (object state) {
                this.End(asyncResult);
            }, null);
        }

        protected virtual void RaiseCompletionPropertyChanges()
        {
            if (this.User != null)
            {
                base.RaisePropertyChanged("User");
            }
        }

        private void RunInSynchronizationContext(SendOrPostCallback callback, object state)
        {
            if (SynchronizationContext.Current == this._synchronizationContext)
            {
                callback(state);
            }
            else
            {
                this._synchronizationContext.Post(callback, state);
            }
        }

        internal void Start()
        {
            this._asyncResult = this.BeginCore(new AsyncCallback(this.HandleAsyncCompleted));
        }

        protected IAsyncResult AsyncResult
        {
            get
            {
                return this._asyncResult;
            }
        }

        protected AuthenticationResult Result
        {
            get
            {
                return (AuthenticationResult) base.Result;
            }
        }

        protected AuthenticationService Service
        {
            get
            {
                return this._service;
            }
        }

        protected override bool SupportsCancellation
        {
            get
            {
                return this.Service.SupportsCancellation;
            }
        }

        public IPrincipal User
        {
            get
            {
                if (this.Result != null)
                {
                    return this.Result.User;
                }
                return null;
            }
        }
    }
}

